package cn.amaake.magicplugin.nacos.service;

import cn.amaake.magicplugin.nacos.config.NacosConfig;
import cn.hutool.core.util.StrUtil;
import org.apache.dubbo.config.*;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.rpc.service.GenericService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.ssssssss.magicapi.core.model.*;
import org.ssssssss.magicapi.core.service.MagicAPIService;
import org.ssssssss.magicapi.core.service.MagicResourceService;
import org.ssssssss.magicapi.function.model.FunctionInfo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



public class DobboService {

    private final Logger logger = LoggerFactory.getLogger(DobboService.class);
    private MagicAPIService magicAPIService;
    private MagicResourceService magicResourceService;
    private ApplicationContext applicationContext;
    private NacosConfig nacosConfig;
    private RegistryConfig registryConfig;
    private ConfigCenterConfig configCenterConfig;
    private ProtocolConfig protocol;
    private Map<String, ServiceConfig<GenericService>> serviceConfigMap = new HashMap<>();
    private List<ServiceConfig> serviceConfigList = new ArrayList<>();

    public DobboService(ApplicationContext applicationContext, NacosConfig nacosConfig, MagicAPIService magicAPIService, MagicResourceService magicResourceService){
        this.applicationContext = applicationContext;
        this.nacosConfig = nacosConfig;
        this.magicAPIService = magicAPIService;
        this.magicResourceService = magicResourceService;
        initRegistryConfig();
        initService();
    }

    private void initRegistryConfig(){
        registryConfig = new RegistryConfig();
        registryConfig.setAddress("nacos://"+nacosConfig.getServerAddr());
        configCenterConfig = new ConfigCenterConfig();
        configCenterConfig.setAddress("nacos://"+nacosConfig.getServerAddr());
        if(StrUtil.isNotEmpty(nacosConfig.getNamespace())){
            Map<String,String> parameters = new HashMap<>();
            parameters.put("namespace",nacosConfig.getNamespace());
            registryConfig.setParameters(parameters);
            configCenterConfig.setParameters(parameters);
        }
        registryConfig.setGroup(nacosConfig.getGroup());
        if (nacosConfig.isEnabledAuth()){
            registryConfig.setUsername(nacosConfig.getUsername());
            registryConfig.setPassword(nacosConfig.getPassword());
            configCenterConfig.setUsername(nacosConfig.getUsername());
            configCenterConfig.setPassword(nacosConfig.getPassword());
        }
        // 服务提供者协议配置
        protocol = new ProtocolConfig();
        protocol.setName(nacosConfig.getDubboProtocolName());
        protocol.setPort(nacosConfig.getDubboProtocolPort());
        protocol.setThreads(nacosConfig.getDubboProtocolThreads());
    }


    //@PostConstruct
    private void initService(){
        magicResourceService.refresh();
        TreeNode<Group> funtionTreeNode = magicResourceService.tree("function");
        List<TreeNode<Group>> children = funtionTreeNode.getChildren();



        for(TreeNode<Group> a : children){
            String nodeid = a.getNode().getId();
            //String nodename = a.getNode().getName();
            String nodepath = a.getNode().getPath();
            List<FunctionInfo> functionlists = magicResourceService.listFiles(nodeid);
            String serviceName = nodepath.replace("/","");
            GenericService genericService = new MagicApiGenericService(serviceName,magicAPIService,functionlists);
            registerService(serviceName,genericService,false);
        }

        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(5000);

        // 通过DubboBootstrap简化配置组装，控制启动过程
        Environment env = applicationContext.getEnvironment();
        DubboBootstrap dubboBootstrap = DubboBootstrap.getInstance()
                .application(env.getProperty("spring.application.name")+"-rpc") // 应用配置
                .registry(registryConfig) // 注册中心配置
                .provider(providerConfig)
                .configCenter(configCenterConfig)
                .protocol(protocol) // 全局默认协议配置
                .services(serviceConfigList)
                .start();    // 启动Dubbo
//                //.await();   // 挂起等待(防止进程退出）


    }



    private ServiceConfig registerService(String serviceName, GenericService genericService,boolean ifddfb){
        ServiceConfig<GenericService> service = new ServiceConfig<>();
        if(ifddfb){
            service.setRegistry(registryConfig);
        }
        // 弱类型接口名
        service.setInterface(nacosConfig.getDubboPrefix()+serviceName);
        service.setVersion("1.0.0");
        if(ifddfb) {
            Environment env = applicationContext.getEnvironment();
            service.setApplication(new ApplicationConfig(env.getProperty("spring.application.name") + "-rpc"));
        }
        // 指向一个通用服务实现
        service.setRef(genericService);
        if(ifddfb) {
            service.setConfigCenter(configCenterConfig);
            service.setProtocol(protocol);
        }
        if(ifddfb) {
            service.export();
        }
        //unexport() 停止
        serviceConfigMap.put(serviceName, service);
        serviceConfigList.add(service);
        return service;
    }

    public void unexport(String ServiceName){
        serviceConfigMap.get(ServiceName).unexport();
    }

    public Map<String, ServiceConfig<GenericService>> getServiceConfigMap() {
        return serviceConfigMap;
    }

    public void setServiceConfigMap(Map<String, ServiceConfig<GenericService>> serviceConfigMap) {
        this.serviceConfigMap = serviceConfigMap;
    }
}
